/**
 * 
 */
package cn.terrence.myrpc.common.nio;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author wuchuang
 * 2018年1月10日下午3:06:26
 */
public class NIO {
	
	private int ports[];
	private ByteBuffer echoBuffer = ByteBuffer.allocate(1024);
	
	public NIO(int[] ports) {
		super();
		this.ports = ports;
	}

	@SuppressWarnings({ "unused", "rawtypes" })
	private void startup() throws Exception{
		Selector selector = Selector.open();
		for(int index=0,length=ports.length;index<length;index++){
			ServerSocketChannel ssc = ServerSocketChannel.open();
			ssc.configureBlocking(false);
			ServerSocket ss = ssc.socket();
			InetSocketAddress address = new InetSocketAddress(ports[index]);
			ss.bind(address);
			SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
	        System.out.println("Going to listen on " + ports[index]);
		}
		while(true){
			int num = selector.select();
			Set selectedKeys = selector.selectedKeys();
			Iterator it = selectedKeys.iterator();
			while(it.hasNext()){
				SelectionKey key = (SelectionKey) it.next();
				if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
					ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
					SocketChannel sc = ssc.accept();
					sc.configureBlocking(false);
					SelectionKey newKey = sc.register(selector,SelectionKey.OP_READ);
					it.remove();
					System.out.println("Got connection from " + sc);
				}else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ){
                    SocketChannel sc = (SocketChannel) key.channel();
                    int bytesEchoed = 0;
                    while (true) {
                         echoBuffer.clear();
                         int r = sc.read(echoBuffer);
                         if (r <= 0) {
                              break;
                         }
                         echoBuffer.flip();
                         sc.write(echoBuffer);
                         bytesEchoed += r;
                    }
                    System.out.println("Echoed " + bytesEchoed + " from " + sc);
                    it.remove();
				}
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int[] ports = new int[]{8080,8081,8082};
		try {
			new NIO(ports).startup();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
